local _M = { }

local str_find = string.find
local ngx_re_match = ngx.re.match
local str_gsub = string.gsub

function _M.challenge_windows(ua, result)
  if not str_find(ua, 'Windows', 1, true) then
    return false;
  end

  if str_find(ua, 'Xbox', 1, true) then
    if str_find(ua, 'Xbox; Xbox One)', 1, true) then
    	result['os'] = 'XboxOne'
    else
    	result['os'] = 'Xbox360'
    end
    return true
  end

  local match, err = ngx_re_match(ua, 'Windows ([ .a-zA-Z0-9]+)[;)]', "o")
  if not match then
    result['os'] = 'Windows'
    return true
  end
  local osn = 'Windows'
  local version = match[1]
  if version == 'NT 10.0' then
    --data = dataset.get('Win10')
  elseif version == 'NT 6.3' then
    --data = dataset.get('Win8.1')
  elseif version == 'NT 6.2' then
    --data = dataset.get('Win8') -- "NT 6.2; ARM;" means Windows RT, oh....
  elseif version == 'NT 6.1' then
    --data = dataset.get('Win7')
  elseif version == 'NT 6.0' then
    --data = dataset.get('WinVista')
  elseif version == 'NT 5.1' then
    --data = dataset.get('WinXP')
  elseif version == 'NT 5.0' then
    --data = dataset.get('Win2000')
  elseif version == 'NT 4.0' then
    --data = dataset.get('WinNT4')
  elseif version == '98' then
    --data = dataset.get('Win98')
  elseif version == '95' then
    --data = dataset.get('Win95')
  elseif version == 'CE' then
    --data = dataset.get('WinCE')
  else
    match, err = ngx_re_match(version, [[^Phone(?: OS)? ([.0-9]+)]], "o")
    if match then
    	osn = 'WinPhone'
      --data = dataset.get('WinPhone')
      version = match[1]
    end
  end
  result['os'] = osn
  result['os_version'] = version
  return true;
end

function _M.challenge_osx(ua, result)
  -- Opens a file in append mode

  if not str_find(ua, 'Mac OS X', 1, true) then
    return false
  end

  local dummy = nil
  --local data = dataset.get('OSX');
  local version = nil
  local osn = 'iOS'
  local match = nil

  if str_find(ua, 'like Mac OS X', 1, true) then
    if str_find(ua, 'iPhone;', 1, true) then
      --data = dataset.get('iPhone')
    elseif str_find(ua, 'iPad;', 1, true) then
      --data = dataset.get('iPad')
    elseif str_find(ua, 'iPod', 1, true) then
      --data = dataset.get('iPod')
    end

    local match, err = ngx_re_match(ua, [[; CPU(?: iPhone)? OS (\d+_\d+(?:_\d+)?) like Mac OS X]], "o")
    if match and match[1] then
      version, dummy = str_gsub(match[1], "_", ".")
    end

  else
  	osn = 'MacOS'
    local match, err = ngx_re_match(ua, [[Mac OS X (10[._]\d+(?:[._]\d+)?)(?:\)|;)]], "o")
    if match and match[1] then
      version, dummy = str_gsub(match[1], "_", ".")
    end
  end
  result['os'] = osn
  result['os_version'] = version
  return true
end


function _M.challenge_linux(ua, result)
  if not str_find(ua, 'Linux', 1, true) then
    return false
  end

  --local data = dataset.get('Linux');
  local osn = 'Linux'
  local os_version = nil

  if str_find(ua, 'Android', 1, true) then
    osn = 'Android'
    local match, err = ngx_re_match(ua, [[Android[- ](\d+(.\d+(?:.\d+)?)?)]], "o")
    if match then
      os_version = match[1]
    end
  end

  result['os'] = osn
  result['os_version'] = os_version
  return true
end


function _M.challenge_smart_phone(ua, result)
  local osn, os_version, match, err = nil

  if str_find(ua, 'iPhone', 1, true) then
  	osn = 'iOS'
    --data = dataset.get('iPhone')
  elseif str_find(ua, 'iPad', 1, true) then
  	osn = 'iOS'
    --data = dataset.get('iPad')
  elseif str_find(ua, 'iPod', 1, true) then
  	osn = 'iOS'
    --data = dataset.get('iPod')
  elseif str_find(ua, 'Android', 1, true) then
  	osn = 'Android'
    --data = dataset.get('Android')
  elseif str_find(ua, 'CFNetwork', 1, true) then
    --data = dataset.get('iOS')
    osn = 'iOS'
  elseif str_find(ua, 'BB10', 1, true) then
    --data = dataset.get('BlackBerry10')
    osn = 'BlackBerry'
    match, err = ngx_re_match(ua, [[Version/([.0-9]+) ]], "o")
    if match then
      os_version = match[1]
    end
  elseif str_find(ua, 'BlackBerry', 1, true) then
    --data = dataset.get('BlackBerry')
    osn = 'BlackBerry'
    match, err = ngx_re_match(ua, [[BlackBerry(?:\d+)/([.0-9]+) ]], "o")
    if match then
      os_version = match[1]
    end
  else
  	match, err = ngx_re_match(ua, [[^Mozilla/[.0-9]+ \((?:Mobile|Tablet);(?:.*;)? rv:([.0-9]+)\) Gecko/[.0-9]+ Firefox/[.0-9]+$]], "o")
    if match then
      --data = dataset.get('FirefoxOS');
      osn = 'FirefoxOS'
      os_version = match[1]
    end
  end

  if not osn then
    return false
  end

  result['os'] = osn
  result['os_version'] = os_version
  return true
end

function _M.challenge_mobile_phone(ua, result)
  if str_find(ua, 'KDDI-', 1, true) then
    local match, err = ngx_re_match(ua, [[KDDI-([^- /;()"']+)]], "o")
    if match then
      local term = match[1];
      result['os'] = 'au'
      result['os_version'] = term
      return true
    end
  elseif str_find(ua, 'WILLCOM', 1, true) or str_find(ua, 'DDIPOCKET', 1, true) then
    local match, err = ngx_re_match(ua, [[(?:WILLCOM|DDIPOCKET);[^/]+/([^ /;()]+)]], "o")
    if match then
      local term = match[1];
      result['os'] = 'WILLCOM'
      result['os_version'] = term
      return true
    end
  elseif str_find(ua, 'SymbianOS', 1, true) then
    result['os'] = 'SymbianOS'
    return true
  elseif str_find(ua, 'Google Wireless Transcoder', 1, true) then
    result['os'] = 'Mobile Transcoder'
    return true
  elseif str_find(ua, 'Naver Transcoder', 1, true) then
    result['os'] = 'Mobile Transcoder'
    result['os_version'] = 'Naver'
    return true
  end

  return false
end

function _M.challenge_appliance(ua, result)
  if str_find(ua, 'Nintendo DSi;', 1, true) then
    local data = dataset.get('NintendoDSi');
    result['os'] = 'Nintendo DSi'
    return true
  elseif str_find(ua, 'Nintendo Wii;', 1, true) then
    local data = dataset.get('NintendoWii');
    result['os'] = 'Nintendo Wii U'
    return true
  end

  return false
end

function _M.challenge_misc(ua, result)
  local osn, os_version, match, err = nil

  if str_find(ua, '(Win98;', 1, true) then
    --data = dataset.get('Win98');
    osn = 'Windows'
    os_version = '98'
  elseif str_find(ua, 'Macintosh; U; PPC;', 1, true) then
    --data = dataset.get('MacOS');
    osn = 'MacOS'
    match, err = ngx_re_match(ua, [[rv:(\d+.\d+.\d+)]], "o")
    if match then
      os_version = match[1]
    end
  elseif str_find(ua, 'Mac_PowerPC', 1, true) then
    --data = dataset.get('MacOS');
    osn = 'MacOS'
  elseif str_find(ua, 'X11; FreeBSD ', 1, true) then
    --data = dataset.get('BSD');
    osn = 'Unix'
    match, err = ngx_re_match(ua, [[FreeBSD ([^;\)]+);]], "o")
    if match then
      os_version = match[1]
    end
  elseif str_find(ua, 'X11; CrOS ', 1, true) then
    --data = dataset.get('ChromeOS');
    osn = 'ChromeOS'
    match, err = ngx_re_match(ua, [[CrOS ([^\)]+)\)]], "o")
    if match then
      os_version = match[1]
    end
  end

  if osn then
    result['os'] = osn
  	result['os_version'] = os_version
    return true
  end

  return false
end

return _M
